[ICPC 2026 Wuhan I] Prime Game 博弈
题目描述
彩叶和辉夜最近迷上了一个基于质数的博弈游戏。
起初,她们共有一个正整数 。两人将轮流进行操作,彩叶与辉夜各完成一次操作视为一个回合。在每一个回合中:
- 彩叶先手:她需要选择一个非负整数 (),并将当前的 替换为 。
- 辉夜后手:她需要选择一个能整除当前 的质数 (即 ),并将当前的 替换为 。
以上操作会不断重复,直到某个回合结束后,若 ,则游戏立即结束。
在游戏过程中,彩叶希望最大化游戏进行的总回合数,而辉夜希望最小化总回合数。假设双方都足够聪明并采取最优策略,请你求出游戏最终会进行多少个回合。
输入格式
第一行包含一个整数 (),表示游戏初始的数字。
输出格式
输出一行包含一个整数,表示在双方都采取最优策略的情况下,游戏最终进行的总回合数。
输入输出样例 #1
输入 #1
1
输出 #1
0
输入输出样例 #2
输入 #2
9
输出 #2
4
输入输出样例 #3
输入 #3
16
输出 #3
5
题解
思考
可以发现当 n 为 、1、2 时游戏会在这一轮结束,其他情况彩叶可以把 n 变为合数使游戏继续。这里很容易想到结果和 n 的质因数有关。辉夜会使 n 和它质因数数量不断减少,而彩叶要使 n 尽可能大,质因数数量尽可能多。
- 结论:回合数随 n 单调不降。当彩叶选择了最优操作,比当前 n 更大的数至少也能够支持她选择更优的操作、更大的n 也使得需要花更多回合使它变成 、1、2。
那么彩叶就需要每次操作完 n 的最大质因子尽可能小,让下一轮的 n 尽可能大。2 是最小的质数,但有时凑不到 2 倍数的合数,可以凑到 3 倍数的。因此选择形如 且除完最大质因数最大的那个数。
预处理出这些数及其结果,不断迭代计算即可。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
int n;
cin >> n;
vector<int> s,m;
for (int u=1;u<=2ll*n;u*=3ll) {
for (int v=u;v<=2ll*n;v*=2ll) {
s.push_back(v);
}
}
sort(s.begin(), s.end());
for (int i:s) {
if (i%3==0) m.push_back(i/3);
else m.push_back(i/2);
}
int cnt = 0;
while (n!=1) {
cnt++;
auto it = lower_bound(s.begin(), s.end(), n);
int v = -1;
for (;it!=s.end() && *it<n*2;++it) {
if (m[it-s.begin()]>v) v = m[it-s.begin()];
}
n = v;
}
cout << cnt << "\n";
return 0;
}
注意
- 这里通过迭代法枚举所有可能的数,我一开始犯傻用
dfs又不会优化直接MLE。 - 用
vector记录数值,我一开始还用了set和unordered_map,直接TLE… - 看题解时看到了一段注释:
// 生命如同戏剧,你永远预料不到转折出现在哪一篇章。
// 世间的奇遇之所以存在,就是为了给世人带来转机。
- 感谢提供题解的大佬们
- 好郁闷啊,我真的区完了…